package com.iemp.advice;

import com.iemp.exception.AbstractStateExceptionHandler;
import com.iemp.exception.entity.base.AbstractStateException;
import com.iemp.exception.entity.sql.CustomSQLException;
import com.iemp.result.JsonResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.sql.SQLIntegrityConstraintViolationException;

/* 常规 ResponseBody 预处理 */
// 若不指定 basePackage ， 则会预处理 Swagger2Controller 中的接口，导致 Swagger2 不可用
@RestControllerAdvice(basePackages = {"com.iemp.web.controller.normal"}, basePackageClasses = JsonResultResponseAdvice.class)
public final class JsonResultResponseAdvice implements ResponseBodyAdvice<Object>, AbstractStateExceptionHandler {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    /* 开启预处理 */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    /* 返回对象前预处理 */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        /* 若将要返回的 body 为 ExceptionWithStaete, 则将其 state 和 message 读出 */
        if (body instanceof AbstractStateException) {
            return JsonResult.create((AbstractStateException) body);
        }
        return JsonResult.create(body);
    }

    @Override
    public AbstractStateException exceptionWithState(AbstractStateException exception) {
        return exception;
    }

        @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public AbstractStateException SQLIntegrityConstraintViolationException(SQLIntegrityConstraintViolationException e) {
        log.error("sql exception:{}", e.getMessage());
        return new CustomSQLException(e.getMessage());
    }
}
